using System;
using System.Collections.Generic;
using System.Text;
using NUnit.Framework;
using FriendsNearby.Services.Entities;
using InSTEDD.Labs.Geo;
using FriendsNearby.Services.Facebook;
using Facebook.Service;
using Moq;

namespace FriendsNearby.Services.Tests
{
	[TestFixture]
	public class PeopleNearbyServiceFixture
	{
		PeopleNearbyService peopleNearbyService;
		Mock<ILocationService> locationService;
		Mock<ISocialNetworkService> socialNetworkService;
		Mock<IUsersService> usersService;
		Guid me = Guid.Empty;
		Guid b1 = Guid.NewGuid();
		Guid b2 = Guid.NewGuid();
		Guid b3 = Guid.NewGuid();

		[SetUp]
		public void SetUp()
		{
			locationService = new Mock<ILocationService>();
			socialNetworkService = new Mock<ISocialNetworkService>();
			usersService = new Mock<IUsersService>();
			peopleNearbyService = new PeopleNearbyService(locationService.Object, usersService.Object, socialNetworkService.Object);
		}

		[Test]
		public void MyFriendsWithVisibiltyFriendsAndTheirFriendsAreShown()
		{
			socialNetworkService.Expect(x=> x.GetFriends(me)).Returns(
				Utils.List<Guid>(b1,  b2, b3));
			socialNetworkService.Expect(x=>x.GetFriendsOfFriends(me)).Returns(
				Utils.List<Guid>());

			locationService.Expect(x => x.GetCurrentLocation(me)).Returns(
				new LocationInfo { UserID = me, Location = new LatLong(0, 0) });
			locationService.Expect(x => x.GetCurrentLocation(b1)).Returns(
				new LocationInfo { UserID = b1, Location = new LatLong(0, 1) });
			locationService.Expect(x => x.GetCurrentLocation(b2)).Returns(
				new LocationInfo { UserID = b2, Location = new LatLong(0, 2) });
			locationService.Expect(x => x.GetCurrentLocation(b3)).Returns(
				new LocationInfo { UserID = b3, Location = new LatLong(0, 3) });

			usersService.Expect(x => x.GetUserPreferences(me)).Returns(
				new UserRegistry { UserID = me, NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.Everyone });
			usersService.Expect(x => x.GetUserPreferences(b1)).Returns(
				new UserRegistry { UserID = b1, NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.ContactsAndTheirContacts });
			usersService.Expect(x => x.GetUserPreferences(b2)).Returns(
				new UserRegistry { UserID = b2, NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.ContactsAndTheirContacts });
			usersService.Expect(x => x.GetUserPreferences(b3)).Returns(
				new UserRegistry { UserID = b3, NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.ContactsAndTheirContacts });

			List<PersonNearby> persons = new List<PersonNearby>(peopleNearbyService.GetContacts(me, QueryContactsKind.Nearby));

			Assert.AreEqual(3, persons.Count);
			Assert.IsFalse(Utils.GetPersonNearby(persons, b1).IsHidden);
			Assert.IsFalse(Utils.GetPersonNearby(persons, b2).IsHidden);
			Assert.IsFalse(Utils.GetPersonNearby(persons, b3).IsHidden);

			Assert.AreEqual(0, Utils.GetPersonNearby(persons, b1).Location.Lat);
			Assert.AreEqual(1, Utils.GetPersonNearby(persons, b1).Location.Long);

			Assert.AreEqual(PersonNearbyRelation.Friend, Utils.GetPersonNearby(persons, b1).Relation);
		}

		[Test]
		public void MyFriendsWithVisibiltyOnlyFriendsAreShown()
		{
			socialNetworkService.Expect(x => x.GetFriends(me)).Returns(
				Utils.List<Guid>(b1, b2, b3));
			socialNetworkService.Expect(x => x.GetFriendsOfFriends(me)).Returns(
				Utils.List<Guid>());

			locationService.Expect(x => x.GetCurrentLocation(me)).Returns(
				new LocationInfo { UserID = me, Location = new LatLong(0, 0) });
			locationService.Expect(x => x.GetCurrentLocation(b1)).Returns(
				new LocationInfo { UserID = b1, Location = new LatLong(0, 1) });
			locationService.Expect(x => x.GetCurrentLocation(b2)).Returns(
				new LocationInfo { UserID = b2, Location = new LatLong(0, 2) });
			locationService.Expect(x => x.GetCurrentLocation(b3)).Returns(
				new LocationInfo { UserID = b3, Location = new LatLong(0, 3) });

			usersService.Expect(x => x.GetUserPreferences(me)).Returns(
				new UserRegistry { UserID = me, NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.Everyone });
			usersService.Expect(x => x.GetUserPreferences(b1)).Returns(
				new UserRegistry { UserID = b1, NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.OnlyFriends });
			usersService.Expect(x => x.GetUserPreferences(b2)).Returns(
				new UserRegistry { UserID = b2, NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.OnlyFriends});
			usersService.Expect(x => x.GetUserPreferences(b3)).Returns(
				new UserRegistry { UserID = b3, NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.OnlyFriends});

			List<PersonNearby> persons = new List<PersonNearby>(peopleNearbyService.GetContacts(me, QueryContactsKind.Nearby));

			Assert.AreEqual(3, persons.Count);
			Assert.IsFalse(Utils.GetPersonNearby(persons, b1).IsHidden);
			Assert.IsFalse(Utils.GetPersonNearby(persons, b2).IsHidden);
			Assert.IsFalse(Utils.GetPersonNearby(persons, b3).IsHidden);

			Assert.AreEqual(0, Utils.GetPersonNearby(persons, b1).Location.Lat);
			Assert.AreEqual(1, Utils.GetPersonNearby(persons, b1).Location.Long);
		}

		[Test]
		public void MyFriendsWithVisibiltyNobodyAreNotShown()
		{
			socialNetworkService.Expect(x => x.GetFriends(me)).Returns(
				Utils.List<Guid>(b1, b2, b3));
			socialNetworkService.Expect(x => x.GetFriendsOfFriends(me)).Returns(
				Utils.List<Guid>());

			locationService.Expect(x => x.GetCurrentLocation(me)).Returns(
				new LocationInfo { UserID = me, Location = new LatLong(0, 0) });
			locationService.Expect(x => x.GetCurrentLocation(b1)).Returns(
				new LocationInfo { UserID = b1, Location = new LatLong(0, 1) });
			locationService.Expect(x => x.GetCurrentLocation(b2)).Returns(
				new LocationInfo { UserID = b2, Location = new LatLong(0, 2) });
			locationService.Expect(x => x.GetCurrentLocation(b3)).Returns(
				new LocationInfo { UserID = b3, Location = new LatLong(0, 3) });

			usersService.Expect(x => x.GetUserPreferences(me)).Returns(
				new UserRegistry { UserID = me, NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.Everyone });
			usersService.Expect(x => x.GetUserPreferences(b1)).Returns(
				new UserRegistry { UserID = b1, NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.Nobody });
			usersService.Expect(x => x.GetUserPreferences(b2)).Returns(
				new UserRegistry { UserID = b2, NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.Nobody });
			usersService.Expect(x => x.GetUserPreferences(b3)).Returns(
				new UserRegistry { UserID = b3, NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.Nobody });

			List<PersonNearby> persons = new List<PersonNearby>(peopleNearbyService.GetContacts(me, QueryContactsKind.Nearby));

			Assert.AreEqual(0, persons.Count);
		}

		[Test]
		public void FriendsOfMyFriendsWithVisibiltyFriendsAndTheirFriendsAreShown()
		{
			socialNetworkService.Expect(x => x.GetFriends(me)).Returns(
				Utils.List<Guid>());
			socialNetworkService.Expect(x => x.GetFriendsOfFriends(me)).Returns(
				Utils.List<Guid>(b1, b2, b3));

			locationService.Expect(x => x.GetCurrentLocation(me)).Returns(
				new LocationInfo { UserID = me, Location = new LatLong(0, 0) });
			locationService.Expect(x => x.GetCurrentLocation(b1)).Returns(
				new LocationInfo { UserID = b1, Location = new LatLong(0, 1) });
			locationService.Expect(x => x.GetCurrentLocation(b2)).Returns(
				new LocationInfo { UserID = b2, Location = new LatLong(0, 2) });
			locationService.Expect(x => x.GetCurrentLocation(b3)).Returns(
				new LocationInfo { UserID = b3, Location = new LatLong(0, 3) });

			usersService.Expect(x => x.GetUserPreferences(me)).Returns(
				new UserRegistry { UserID = me, NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.Everyone });
			usersService.Expect(x => x.GetUserPreferences(b1)).Returns(
				new UserRegistry { UserID = b1, NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.Everyone });
			usersService.Expect(x => x.GetUserPreferences(b2)).Returns(
				new UserRegistry { UserID = b2, NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.ContactsAndTheirContacts });
			usersService.Expect(x => x.GetUserPreferences(b3)).Returns(
				new UserRegistry { UserID = b3, NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.ContactsAndTheirContacts });

			List<PersonNearby> persons = new List<PersonNearby>(peopleNearbyService.GetContacts(me, QueryContactsKind.Nearby));

			Assert.AreEqual(3, persons.Count);
			Assert.IsFalse(Utils.GetPersonNearby(persons, b1).IsHidden);
			Assert.IsFalse(Utils.GetPersonNearby(persons, b2).IsHidden);
			Assert.IsFalse(Utils.GetPersonNearby(persons, b3).IsHidden);

			Assert.AreEqual(0, Utils.GetPersonNearby(persons, b1).Location.Lat);
			Assert.AreEqual(1, Utils.GetPersonNearby(persons, b1).Location.Long);

			Assert.AreEqual(PersonNearbyRelation.FriendOfAFriend, Utils.GetPersonNearby(persons, b1).Relation);
		}

		[Test]
		public void FriendsOfMyFriendsWithVisibiltyOnlyFriendsAreShownHidden()
		{
			socialNetworkService.Expect(x => x.GetFriends(me)).Returns(
				Utils.List<Guid>());
			socialNetworkService.Expect(x => x.GetFriendsOfFriends(me)).Returns(
				Utils.List<Guid>(b1, b2, b3));

			locationService.Expect(x => x.GetCurrentLocation(me)).Returns(
				new LocationInfo { UserID = me, Location = new LatLong(0, 0) });
			locationService.Expect(x => x.GetCurrentLocation(b1)).Returns(
				new LocationInfo { UserID = b1, Location = new LatLong(0, 1) });
			locationService.Expect(x => x.GetCurrentLocation(b2)).Returns(
				new LocationInfo { UserID = b2, Location = new LatLong(0, 2) });
			locationService.Expect(x => x.GetCurrentLocation(b3)).Returns(
				new LocationInfo { UserID = b3, Location = new LatLong(0, 3) });

			usersService.Expect(x => x.GetUserPreferences(me)).Returns(
				new UserRegistry { UserID = me, NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.Everyone });
			usersService.Expect(x => x.GetUserPreferences(b1)).Returns(
				new UserRegistry { UserID = b1, NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.OnlyFriends });
			usersService.Expect(x => x.GetUserPreferences(b2)).Returns(
				new UserRegistry { UserID = b2, NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.OnlyFriends });
			usersService.Expect(x => x.GetUserPreferences(b3)).Returns(
				new UserRegistry { UserID = b3, NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.OnlyFriends });

			List<PersonNearby> persons = new List<PersonNearby>(peopleNearbyService.GetContacts(me, QueryContactsKind.Nearby));

			Assert.AreEqual(3, persons.Count);
			Assert.IsTrue(Utils.GetPersonNearby(persons, b1).IsHidden);
			Assert.AreEqual("Unknown 1", Utils.GetPersonNearby(persons, b1).DisplayName);
			Assert.IsTrue(Utils.GetPersonNearby(persons, b2).IsHidden);
			Assert.AreEqual("Unknown 2", Utils.GetPersonNearby(persons, b2).DisplayName);
			Assert.IsTrue(Utils.GetPersonNearby(persons, b3).IsHidden);
			Assert.AreEqual("Unknown 3", Utils.GetPersonNearby(persons, b3).DisplayName);

			Assert.AreEqual(0, Utils.GetPersonNearby(persons, b1).Location.Lat);
			Assert.AreEqual(1, Utils.GetPersonNearby(persons, b1).Location.Long);
		}

		[Test]
		public void FriendsOfMyFriendsWithVisibiltyNobodyAreNotShown()
		{
			socialNetworkService.Expect(x => x.GetFriends(me)).Returns(
				Utils.List<Guid>());
			socialNetworkService.Expect(x => x.GetFriendsOfFriends(me)).Returns(
				Utils.List<Guid>(b1, b2, b3));

			locationService.Expect(x => x.GetCurrentLocation(me)).Returns(
				new LocationInfo { UserID = me, Location = new LatLong(0, 0) });
			locationService.Expect(x => x.GetCurrentLocation(b1)).Returns(
				new LocationInfo { UserID = b1, Location = new LatLong(0, 1) });
			locationService.Expect(x => x.GetCurrentLocation(b2)).Returns(
				new LocationInfo { UserID = b2, Location = new LatLong(0, 2) });
			locationService.Expect(x => x.GetCurrentLocation(b3)).Returns(
				new LocationInfo { UserID = b3, Location = new LatLong(0, 3) });

			usersService.Expect(x => x.GetUserPreferences(me)).Returns(
				new UserRegistry { UserID = me, NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.Everyone });
			usersService.Expect(x => x.GetUserPreferences(b1)).Returns(
				new UserRegistry { UserID = b1, NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.Nobody });
			usersService.Expect(x => x.GetUserPreferences(b2)).Returns(
				new UserRegistry { UserID = b2, NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.Nobody });
			usersService.Expect(x => x.GetUserPreferences(b3)).Returns(
				new UserRegistry { UserID = b3, NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.Nobody });

			List<PersonNearby> persons = new List<PersonNearby>(peopleNearbyService.GetContacts(me, QueryContactsKind.Nearby));

			Assert.AreEqual(0, persons.Count);
		}

		[Test]
		public void MyFriendsAreCountedAndTheNearestDistanceIsShown()
		{
			socialNetworkService.Expect(x => x.GetFriends(me)).Returns(
				Utils.List<Guid>(b1, b2, b3));
			socialNetworkService.Expect(x => x.GetFriendsOfFriends(me)).Returns(
				Utils.List<Guid>());

			locationService.Expect(x => x.GetCurrentLocation(me)).Returns(
				new LocationInfo { UserID = me, Location = new LatLong(0, 0) });
			locationService.Expect(x => x.GetCurrentLocation(b1)).Returns(
				new LocationInfo { UserID = b1, Location = new LatLong(0, 1) });
			locationService.Expect(x => x.GetCurrentLocation(b2)).Returns(
				new LocationInfo { UserID = b2, Location = new LatLong(0, 2) });
			locationService.Expect(x => x.GetCurrentLocation(b3)).Returns(
				new LocationInfo { UserID = b3, Location = new LatLong(0, 3) });

			usersService.Expect(x => x.GetUserPreferences(me)).Returns(
				new UserRegistry { UserID = me, NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.Everyone });
			usersService.Expect(x => x.GetUserPreferences(b1)).Returns(
				new UserRegistry { UserID = b1, NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.Everyone });
			usersService.Expect(x => x.GetUserPreferences(b2)).Returns(
				new UserRegistry { UserID = b2, NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.Everyone });
			usersService.Expect(x => x.GetUserPreferences(b3)).Returns(
				new UserRegistry { UserID = b3, NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.Everyone });

			PeopleNearbySummary summary = peopleNearbyService.GetPeopleNearbySummary(me);

			Assert.AreEqual(3, summary.NearbyFriendCount);
			Assert.AreEqual(LatLong.DistanceInKm(new LatLong(0, 1), new LatLong(0, 0)), summary.NearestDistance);
		}

		[Test]
		public void MyFriendsAreShownNoMatterIfTheyAreInMyNearby()
		{
			socialNetworkService.Expect(x => x.GetFriends(me)).Returns(
				Utils.List<Guid>(b1, b2, b3));
			socialNetworkService.Expect(x => x.GetFriendsOfFriends(me)).Returns(
				Utils.List<Guid>());

			locationService.Expect(x => x.GetCurrentLocation(me)).Returns(
				new LocationInfo { UserID = me, Location = new LatLong(0, 0) });
			locationService.Expect(x => x.GetCurrentLocation(b1)).Returns(
				new LocationInfo { UserID = b1, Location = new LatLong(0, 1) });
			locationService.Expect(x => x.GetCurrentLocation(b2)).Returns(
				new LocationInfo { UserID = b2, Location = new LatLong(0, 2) });
			locationService.Expect(x => x.GetCurrentLocation(b3)).Returns(
				new LocationInfo { UserID = b3, Location = new LatLong(0, 3) });

			usersService.Expect(x => x.GetUserPreferences(me)).Returns(
				new UserRegistry { UserID = me, NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.Everyone });
			usersService.Expect(x => x.GetUserPreferences(b1)).Returns(
				new UserRegistry { UserID = b1, NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.Everyone });
			usersService.Expect(x => x.GetUserPreferences(b2)).Returns(
				new UserRegistry { UserID = b2, NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.Everyone });
			usersService.Expect(x => x.GetUserPreferences(b3)).Returns(
				new UserRegistry { UserID = b3, NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.Everyone });

			List<PersonNearby> persons = new List<PersonNearby>(peopleNearbyService.GetContacts(me, QueryContactsKind.Direct));

			Assert.AreEqual(3, persons.Count);
		}

		[Test]
		public void MyFriendsAreShownIffTheyAreInMyNearby()
		{
			socialNetworkService.Expect(x => x.GetFriends(me)).Returns(
				Utils.List<Guid>(b1, b2));
			socialNetworkService.Expect(x => x.GetFriendsOfFriends(me)).Returns(
				Utils.List<Guid>());

			locationService.Expect(x => x.GetCurrentLocation(me)).Returns(
				new LocationInfo { UserID = me, Location = new LatLong(0, 0) });
			locationService.Expect(x => x.GetCurrentLocation(b1)).Returns(
				new LocationInfo { UserID = b1, Location = new LatLong(0, 2) });
			locationService.Expect(x => x.GetCurrentLocation(b2)).Returns(
				new LocationInfo { UserID = b2, Location = new LatLong(0, 1) });

			usersService.Expect(x => x.GetUserPreferences(me)).Returns(
				new UserRegistry { UserID = me, NearbyRadiusKM = 112, VisibilityLevel = (int)VisibilityLevel.Everyone });
			usersService.Expect(x => x.GetUserPreferences(b1)).Returns(
				new UserRegistry { UserID = b1, NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.Everyone });
			usersService.Expect(x => x.GetUserPreferences(b2)).Returns(
				new UserRegistry { UserID = b2, NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.Everyone });

			List<PersonNearby> persons = new List<PersonNearby>(peopleNearbyService.GetContacts(me, QueryContactsKind.Nearby));
			Assert.AreEqual(1, persons.Count);
		}

		[Test]
		public void ShouldGetListOfFriendsWithoutDistanceIfMyLocationIsNotKnown()
		{
			socialNetworkService.Expect(x => x.GetFriends(me)).Returns(
				Utils.List<Guid>(b1, b2));
			socialNetworkService.Expect(x => x.GetFriendsOfFriends(me)).Returns(
				Utils.List<Guid>());

			locationService.Expect(x => x.GetCurrentLocation(me)).Returns(new LocationInfo() { UserID = me });
			locationService.Expect(x => x.GetCurrentLocation(b1)).Returns(
				new LocationInfo { UserID = b1, Location = new LatLong(0, 2) });
			locationService.Expect(x => x.GetCurrentLocation(b2)).Returns(
				new LocationInfo { UserID = b2, Location = new LatLong(0, 1) });

			usersService.Expect(x => x.GetUserPreferences(me)).Returns(
				new UserRegistry { UserID = me, NearbyRadiusKM = 112, VisibilityLevel = (int)VisibilityLevel.Everyone });
			usersService.Expect(x => x.GetUserPreferences(b1)).Returns(
				new UserRegistry { UserID = b1, NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.Everyone });
			usersService.Expect(x => x.GetUserPreferences(b2)).Returns(
				new UserRegistry { UserID = b2, NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.Everyone });

			List<PersonNearby> persons = new List<PersonNearby>(peopleNearbyService.GetContacts(me, QueryContactsKind.Direct));
			Assert.AreEqual(2, persons.Count);
			Assert.IsNull(persons[0].Distance);
			Assert.IsNull(persons[1].Distance);
		}

		[Test]
		public void UnkownAreEnumeratedFromMyLocation()
		{
			socialNetworkService.Expect(x => x.GetFriends(me)).Returns(
				Utils.List<Guid>());
			socialNetworkService.Expect(x => x.GetFriendsOfFriends(me)).Returns(
				Utils.List<Guid>(b3, b2));

			locationService.Expect(x => x.GetCurrentLocation(me)).Returns(
				new LocationInfo { UserID = me, Location = new LatLong(0, 0) });
			locationService.Expect(x => x.GetCurrentLocation(b2)).Returns(
				new LocationInfo { UserID = b2, Location = new LatLong(1, 1) });
			locationService.Expect(x => x.GetCurrentLocation(b3)).Returns(
				new LocationInfo { UserID = b3, Location = new LatLong(0.5, 0.5) });

			usersService.Expect(x => x.GetUserPreferences(me)).Returns(
				new UserRegistry { UserID = me, NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.Everyone });
			usersService.Expect(x => x.GetUserPreferences(b2)).Returns(
				new UserRegistry { UserID = b2, NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.OnlyFriends });
			usersService.Expect(x => x.GetUserPreferences(b3)).Returns(
				new UserRegistry { UserID = b3, NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.OnlyFriends });

			List<PersonNearby> persons = new List<PersonNearby>(peopleNearbyService.GetContacts(me, QueryContactsKind.Nearby));

			Assert.AreEqual(2, persons.Count);
			Assert.AreEqual(b3, persons[0].UserID);
			Assert.AreEqual("Unknown 1", persons[0].DisplayName);
			Assert.AreEqual(b2, persons[1].UserID);
			Assert.AreEqual("Unknown 2", persons[1].DisplayName);

		}

		[Test]
		public void ShouldGetListAllPeople()
		{
			socialNetworkService.Expect(x => x.GetFriends(me)).Returns(
				Utils.List<Guid>(b1, b2));
			socialNetworkService.Expect(x => x.GetFriendsOfFriends(me)).Returns(
				Utils.List<Guid>(b3));

			locationService.Expect(x => x.GetCurrentLocation(me)).Returns(
				new LocationInfo { UserID = me, Location = new LatLong(0, 0) });
			locationService.Expect(x => x.GetCurrentLocation(b1)).Returns(
				new LocationInfo { UserID = b1, Location = new LatLong(0, 2) });
			locationService.Expect(x => x.GetCurrentLocation(b2)).Returns(
				new LocationInfo { UserID = b2, Location = new LatLong(0, 1) });
			locationService.Expect(x => x.GetCurrentLocation(b3)).Returns(
				new LocationInfo { UserID = b3, Location = new LatLong(0, 3) });

			usersService.Expect(x => x.GetUserPreferences(me)).Returns(
				new UserRegistry { UserID = me, NearbyRadiusKM = 0, VisibilityLevel = (int)VisibilityLevel.Everyone });
			usersService.Expect(x => x.GetUserPreferences(b1)).Returns(
				new UserRegistry { UserID = b1, NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.Everyone });
			usersService.Expect(x => x.GetUserPreferences(b2)).Returns(
				new UserRegistry { UserID = b2, NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.Everyone });
			usersService.Expect(x => x.GetUserPreferences(b3)).Returns(
				new UserRegistry { UserID = b3, NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.Everyone });

			List<PersonNearby> persons = new List<PersonNearby>(peopleNearbyService.GetContacts(me, QueryContactsKind.Any));
			Assert.AreEqual(3, persons.Count);
		}

        [Test]
        public void ShouldGetFacebookUserIDs()
        {
            socialNetworkService.Expect(x => x.GetFriends(me)).Returns(
                Utils.List<Guid>(b1, b2));
            socialNetworkService.Expect(x => x.GetFriendsOfFriends(me)).Returns(
                Utils.List<Guid>(b3));

            locationService.Expect(x => x.GetCurrentLocation(me)).Returns(
                new LocationInfo { UserID = me, Location = new LatLong(0, 0) });
            locationService.Expect(x => x.GetCurrentLocation(b1)).Returns(
                new LocationInfo { UserID = b1, Location = new LatLong(0, 2) });
            locationService.Expect(x => x.GetCurrentLocation(b2)).Returns(
                new LocationInfo { UserID = b2, Location = new LatLong(0, 1) });
            locationService.Expect(x => x.GetCurrentLocation(b3)).Returns(
                new LocationInfo { UserID = b3, Location = new LatLong(0, 3) });

            usersService.Expect(x => x.GetUserPreferences(me)).Returns(
                new UserRegistry { UserID = me, FacebookUserId = "1000", NearbyRadiusKM = 0, VisibilityLevel = (int)VisibilityLevel.Everyone });
            usersService.Expect(x => x.GetUserPreferences(b1)).Returns(
                new UserRegistry { UserID = b1, FacebookUserId = "1001", NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.Everyone });
            usersService.Expect(x => x.GetUserPreferences(b2)).Returns(
                new UserRegistry { UserID = b2, FacebookUserId = "1002", NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.Everyone });
            usersService.Expect(x => x.GetUserPreferences(b3)).Returns(
                new UserRegistry { UserID = b3, FacebookUserId = "1003", NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.Everyone });

            List<PersonNearby> persons = new List<PersonNearby>(peopleNearbyService.GetContacts(me, QueryContactsKind.Any));
            Assert.AreEqual(3, persons.Count);
            Assert.AreEqual("1001", Utils.GetPersonNearby(persons, b1).FacebookUserID);
            Assert.AreEqual("1002", Utils.GetPersonNearby(persons, b2).FacebookUserID);
            Assert.AreEqual("1003", Utils.GetPersonNearby(persons, b3).FacebookUserID);
        }

		[Test]
		public void ShouldGetListAllPeopleReturnsUserInfosWithLastUpdatedTime()
		{
			socialNetworkService.Expect(x => x.GetFriends(me)).Returns(
				Utils.List<Guid>(b1, b2));
			socialNetworkService.Expect(x => x.GetFriendsOfFriends(me)).Returns(
				Utils.List<Guid>(b3));

			locationService.Expect(x => x.GetCurrentLocation(me)).Returns(
				new LocationInfo { UserID = me, Location = new LatLong(0, 0) });
			locationService.Expect(x => x.GetCurrentLocation(b1)).Returns(
				new LocationInfo { UserID = b1, Location = new LatLong(0, 2) });
			locationService.Expect(x => x.GetCurrentLocation(b2)).Returns(
				new LocationInfo { UserID = b2, Location = new LatLong(0, 1) });
			locationService.Expect(x => x.GetCurrentLocation(b3)).Returns(
				new LocationInfo { UserID = b3, Location = new LatLong(0, 3) });

			usersService.Expect(x => x.GetUserPreferences(me)).Returns(
				new UserRegistry { UserID = me, NearbyRadiusKM = 0, VisibilityLevel = (int)VisibilityLevel.Everyone });
			usersService.Expect(x => x.GetUserPreferences(b1)).Returns(
				new UserRegistry { UserID = b1, NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.Everyone });
			usersService.Expect(x => x.GetUserPreferences(b2)).Returns(
				new UserRegistry { UserID = b2, NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.Everyone });
			usersService.Expect(x => x.GetUserPreferences(b3)).Returns(
				new UserRegistry { UserID = b3, NearbyRadiusKM = Int32.MaxValue, VisibilityLevel = (int)VisibilityLevel.Everyone });

			List<PersonNearby> persons = new List<PersonNearby>(peopleNearbyService.GetContacts(me, QueryContactsKind.Any));
			Assert.AreEqual(3, persons.Count);
			Assert.AreEqual(null, persons.Find(delegate(PersonNearby pn) { return pn.LastLocationUpdate == null; }));
		}

		[Test]
		public void NewFriendDetected()
		{
			List<PersonNearby> before = new List<PersonNearby>();
			List<PersonNearby> now = new List<PersonNearby>();

			Guid a = Guid.NewGuid();
			Guid b = Guid.NewGuid();
			Guid c = Guid.NewGuid();

			before.Add(new PersonNearby() { UserID = a });
			before.Add(new PersonNearby() { UserID = b });

			now.Add(new PersonNearby() { UserID = a });
			now.Add(new PersonNearby() { UserID = c, DisplayName = "C name" });


			IEnumerable<string> newNearbies = PeopleNearbyService.GetNewFriendsNearby(before, now);

			Assert.IsNotNull(newNearbies);

			var it = newNearbies.GetEnumerator();

			Assert.IsTrue(it.MoveNext());
			Assert.AreEqual("C name", it.Current);
		}
	}
}
